<template>
  <div style="height: 100%">
    <el-card style="height: 100%">
      <!-- 1.面包屑 -->
      <MyBread url="administrator" level1="系统管理" level2="角色管理" />
      <!-- 2.表格 -->
      <el-table
        :data="RoleList"
        border
        style="width: 100%; height: 100vh; margin-top: 25px"
        max-height="850"
      >
        <!-- 3.展开行 -->
        <el-table-column type="expand" width="100%">
          <template slot-scope="scoped">
            <el-row v-for="item1 in scoped.row.children" :key="item1.id">
              <el-col :span="4" style="margin-left: 100px">
                <el-tag
                  type="success"
                  closable
                  @close="deleteRightTag(scoped.row, item1)"
                  >{{ item1.name }}></el-tag
                >
                <i class="el-icon-arrow-right"></i>
              </el-col>
              <el-col :span="18">
                <el-tag
                  type="primary"
                  v-for="item2 in item1.children"
                  :key="item2.id"
                  closable
                  @close="deleteRightTag(scoped.row, item2)"
                  >{{ item2.name }}></el-tag
                >
              </el-col>
            </el-row>
            <!-- 无权限提示 -->
            <span
              style="margin-left: 50px"
              v-if="scoped.row.children.length === 0"
              >未分配权限</span
            >
          </template>
        </el-table-column>
        <el-table-column type="index" label="#"></el-table-column>
        <el-table-column prop="authName" label="角色名称"></el-table-column>
        <el-table-column prop="authDesc" label="角色描述"></el-table-column>
        <el-table-column label="操作">
          <template slot-scope="scoped">
            <el-button
              type="primary"
              icon="el-icon-edit"
              circle
              @click="modifyRoleInfo(scoped.row)"
            ></el-button>
            <el-button
              type="success"
              size="medium"
              round
              plain
              @click="assignPermissionsButton(scoped.row)"
              >分配权限</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <!-- 修改角色信息对话框 -->
      <el-dialog
        title="修改角色信息"
        :visible.sync="dialogVisibleFrom"
        width="440"
      >
        <el-form
          ref="form"
          :model="form"
          label-width="100px"
          :rules="rules"
          hide-required-asterisk
        >
          <el-form-item prop="authName" label="角色名称">
            <el-input v-model="form.authName" readonly></el-input>
          </el-form-item>
          <el-form-item prop="authDesc" label="角色描述">
            <el-input v-model="form.authDesc"></el-input>
          </el-form-item>
        </el-form>
        <div slot="footer">
          <el-button @click="dialogCancel()">取 消</el-button>
          <el-button type="primary" @click="modifyRoleInfoData()"
            >确 定</el-button
          >
        </div>
      </el-dialog>
      <!-- 分配权限对话框 -->
      <el-dialog
        :title="titlePermissions"
        :visible.sync="dialogVisibleRightsTree"
        width="440"
        class="student_form_item"
      >
        <el-tree
          ref="tree"
          :data="treeData"
          :props="props"
          show-checkbox
          node-key="id"
          default-expand-all
          :default-checked-keys="checkedKeys"
        >
        </el-tree>
        <div slot="footer">
          <el-button @click="cancleAssignPermissions">取 消</el-button>
          <el-button type="primary" @click="confirmAssignPermissions"
            >确 定</el-button
          >
        </div>
      </el-dialog>
    </el-card>
  </div>
</template>

<script>
export default {
  name: "Role",
  data() {
    return {
      RoleList: [], // 角色列表
      // 所有权限列表
      RightsList: [
        {
          role: "student",
          roleId: 0,
        },
        {
          role: "coach",
          roleId: -1,
        },
        {
          role: "administrator",
          roleId: -2,
        },
      ],
      titlePermissions: "", // 分配权限标题
      dialogVisibleFrom: false, // 控制表单对话框的显隐
      // 角色信息表单
      form: {
        authName: "",
        authDesc: "",
        authNameEN: "administrator",
        authId: -2,
        children: [],
      },
      // 角色表单规则
      rules: {
        authDesc: [
          { required: true, message: "角色描述不能为空", trigger: "blur" },
        ],
      },
      // 树形组件相关数据
      dialogVisibleRightsTree: false, // 树形对话框框的显隐
      // 树形组件属性配置
      props: {
        label: "name",
        children: "children",
      },
      treeData: [], // 树形组件数据
      checkedKeys: [], // 树形组件默认选中的键
      CurrentRoleInfo: [], // 当前角色信息，包括权限
    };
  },
  methods: {
    // 隐藏对话框 -- 重新获取数据
    dialogCancel() {
      this.dialogVisibleFrom = false;
      // 重新获取角色信息
      this.$https.getRoles().then((res) => {
        this.RoleList = res.data;
      });
    },
    // 删除标签 -- 删除权限
    async deleteRightTag(row, item) {
      if (!(await this.haveThisPermission(this.$route.path, "删除角色权限"))) {
        this.$message.warning("您当前没有该权限");
        return;
      }
      this.$confirm("是否删除该权限?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          if (item.delete === false) {
            this.$message.warning("该一级权限不能删除");
            return;
          }
          // 根据功能判断是否可以删除 -- 若功能是查看则不能删除
          if (item.ability === "GET") {
            this.$message.warning("该二级权限不能删除，请删除对应的一级权限");
            return;
          }
          // 若删除的权限是角色管理或修改角色权限
          // 也可以弹出提示框确认管理员是否删除，一旦删除，
          // 想要找回必须通过数据库添加权限
          if (item.name === "角色管理" || item.name === "添加角色权限") {
            this.$message.warning("该管理员权限不能删除");
            return;
          }
          // 根据删除的 Tag 删除对应数据，更新一条数据
          row.children.forEach((element, index) => {
            // 判断删除的是否为一级权限
            if (item.level === 0) {
              // 找到要删除的 Tag标签
              if (element.id === item.id) {
                // 一级权限的删除
                row.children.splice(index, 1);
                return;
              }
            } else {
              // 二级权限的删除
              element.children.forEach((ele, subindex) => {
                if (ele.id === item.id) {
                  element.children.splice(subindex, 1);
                  return;
                }
              });
            }
          });
          // 修改数据库，直接修改整条记录
          this.$https.updateUserData("/role", row.id, row).then(() => {
            this.$message.success(`删除${row.authName}权限成功`);
            this.deleteDisabledProperty();
          });
        })
        .catch(() => {
          this.$message.info("已取消退出");
        });
    },
    // 修改角色信息 -- 显示对话框 + 权限验证
    async modifyRoleInfo(row) {
      if (!(await this.haveThisPermission(this.$route.path, "修改角色"))) {
        this.$message.warning("您当前没有该权限");
        return;
      }
      // 回滚显示信息
      this.form = row;
      this.dialogVisibleFrom = true;
    },
    // 修改角色信息 -- 修改数据库数据
    modifyRoleInfoData() {
      this.$refs["form"].validate(async (valid) => {
        if (valid) {
          await this.$https.updateUserData("/role", this.form.id, this.form);
          this.dialogVisibleFrom = false;
          this.$message.success(`修改${this.form.authName}信息成功`);
          // 表单重置
          this.form = {
            authNameEN: "administrator",
            authId: -2,
            children: [],
          };
        } else {
          this.$message.warning("表单验证不通过");
        }
      });
    },
    // 分配权限 -- 添加权限
    assignPermissionsButton(row) {
      this.deleteDisabledProperty();
      this.CurrentRoleInfo = row;
      // 对显示的权限进行二次加工，即已有的权限默认禁用
      // 获取当前角色信息以及权限
      const currentRole = this.RightsList.filter(
        (item) => item.role === row.authNameEN
      );
      // 进行一级权限的禁用
      currentRole[0].children.forEach((item) => {
        row.children.forEach((element) => {
          if (element.id === item.id) {
            this.$set(item, "disabled", true);
          }
        });
      });
      // 进行二级权限的禁用
      currentRole[0].children.forEach((item1) => {
        item1.children.forEach((item2) => {
          row.children.forEach((element1) => {
            element1.children.forEach((element2) => {
              if (item2.id === element2.id) {
                this.$set(item2, "disabled", true);
              }
            });
          });
        });
      });
      // 若角色有权限，获取默认选中键
      // 若角色没有权限，进行其他处理
      if (row.children.length !== 0) {
        const array = [];
        row.children.forEach((item) => {
          let arr = item.children.map((ele) => ele.id);
          array.push(...arr);
        });
        this.checkedKeys = array;
      }
      // 在对话框中显示对应角色的所有权限，对已有的权限进行勾选
      this.RightsList.forEach((element) => {
        if (row.authNameEN === element.role) {
          this.treeData = element.children;
          this.titlePermissions = `分配${row.authName}权限`;
          return;
        }
      });
      this.dialogVisibleRightsTree = true;
    },
    // 取消分配权限
    cancleAssignPermissions() {
      this.dialogVisibleRightsTree = false;
      this.deleteDisabledProperty();
    },
    // 确认分配权限
    async confirmAssignPermissions() {
      // 1.获取树形结构中被选中的或半选的键(id)
      const RightsID = [
        ...this.$refs["tree"].getCheckedKeys(),
        ...this.$refs["tree"].getHalfCheckedKeys(),
      ];
      // 判断被勾选或半勾选的元素长度是否为0
      if (RightsID.length !== 0) {
        const array = []; // 存放权限数组
        // 2.根据id从权限列表找到对应数据
        const { data } = await this.$https.getRights();
        RightsID.forEach((id) => {
          data.forEach((item) => {
            // 若找到对应数据，退出内循环，进入下一外循环
            if (item.id === id) {
              array.push(item);
              return;
            }
          });
        });
        // 3.对array数组进行加工，形成一级权限和二级权限结构
        // 3.1 过滤一级权限
        const children = array.filter((item) => item.level === 0);
        // 3.2 过滤二级权限
        const secRights = array.filter((item) => item.level === 1);
        // 3.3 对每一个一级权限对象添加children属性
        children.forEach((item) => {
          item.children = [];
        });
        // 3.4 形成层级结构
        children.forEach((item) => {
          secRights.forEach((element) => {
            if (element.pid === item.id) {
              item.children.push(element);
              return;
            }
          });
        });
        // 4.更新 CurrentRoleInfo中children数据
        this.CurrentRoleInfo.children = children;
      } else {
        this.CurrentRoleInfo.children = [];
      }
      // 5.发送请求修改数据库数据
      await this.$https.updateUserData(
        "/role",
        this.CurrentRoleInfo.id,
        this.CurrentRoleInfo
      );
      this.$message.success(`添加${this.CurrentRoleInfo.authName}权限成功`);
      this.deleteDisabledProperty();
      this.dialogVisibleRightsTree = false;
    },
    // 删除权限所有对象中的disabled属性
    deleteDisabledProperty() {
      // 删除成功后去除disabled属性
      this.RightsList.forEach((item) => {
        item.children.forEach((item2) => {
          if (item2.hasOwnProperty("disabled")) {
            this.$delete(item2, "disabled");
            item2.children.forEach((item3) => {
              if (item3.hasOwnProperty("disabled")) {
                this.$delete(item3, "disabled");
              }
            });
          }
        });
      });
    },
  },
  mounted() {
    // 获取角色信息
    this.$https.getRoles().then((res) => {
      this.RoleList = res.data;
    });
    // 获取并加工所有权限信息
    this.$https.getRights().then((res) => {
      this.RightsList.forEach((element) => {
        element.children = res.data.filter((ele) => ele.pid === element.roleId);
        element.children.forEach((ele) => {
          ele.children = res.data.filter((item) => item.pid === ele.id);
        });
      });
    });
  },
};
</script>